﻿using PmSoft.Core.Extensions;
using System.Reflection;

namespace PmSoft.Core.Domain.Auth;

/// <summary>
/// 用于标识用户的类，支持多租户应用程序中的用户标识。
/// </summary>
[Serializable]
public class UserIdentifier : IUserIdentifier
{
	/// <summary>
	/// 用户的租户类型。
	/// 在多租户应用程序中，对于主机用户可以为 null。
	/// </summary>
	public string? TenantType { get; protected set; }
	/// <summary>
	/// 用户的 ID。
	/// </summary>
	public int UserId { get; protected set; }
	/// <summary>
	/// 初始化 <see cref="UserIdentifier"/> 类的新实例（受保护的默认构造函数）。
	/// </summary>
	protected UserIdentifier()
	{
	}
	/// <summary>
	/// 使用指定的租户类型和用户 ID 初始化 <see cref="UserIdentifier"/> 类的新实例。
	/// </summary>
	/// <param name="tenantType">用户的租户类型，可以为 null。</param>
	/// <param name="userId">用户的 ID。</param>
	public UserIdentifier(string? tenantType, int userId)
	{
		TenantType = tenantType;
		UserId = userId;
	}
	public static UserIdentifier Parse(string userIdentifierString)
	{
		if (string.IsNullOrEmpty(userIdentifierString))
		{
			throw new ArgumentNullException(nameof(userIdentifierString), "用户标识字符串不能为 null 或空！");
		}

		string[] parts = userIdentifierString.Split('@');
		return parts.Length switch
		{
			1 => new UserIdentifier(null, parts[0].ConvertTo<int>()),
			2 => new UserIdentifier(parts[1], parts[0].ConvertTo<int>()),
			_ => throw new ArgumentException("用户标识字符串格式不正确", nameof(userIdentifierString))
		};
	}
	public string ToUserIdentifierString()
	{
		return !string.IsNullOrEmpty(TenantType) ? $"{UserId}@{TenantType}" : UserId.ToString();
	}
	public override bool Equals(object? obj)
	{
		if (obj == null || obj is not UserIdentifier other)
		{
			return false;
		}

		if (ReferenceEquals(this, obj))
		{
			return true;
		}

		Type typeOfThis = GetType();
		Type typeOfOther = other.GetType();
		if (!typeOfThis.GetTypeInfo().IsAssignableFrom(typeOfOther) &&
			!typeOfOther.GetTypeInfo().IsAssignableFrom(typeOfThis))
		{
			return false;
		}

		return TenantType == other.TenantType && UserId == other.UserId;
	}
	public override int GetHashCode()
	{
		int hash = 17;
		hash = !string.IsNullOrEmpty(TenantType) ? hash * 23 + TenantType.GetHashCode() : hash;
		hash = hash * 23 + UserId.GetHashCode();
		return hash;
	}
	/// <summary>
	/// 判断两个 <see cref="UserIdentifier"/> 对象是否相等。
	/// </summary>
	/// <param name="left">左侧对象。</param>
	/// <param name="right">右侧对象。</param>
	/// <returns>如果相等则返回 true，否则返回 false。</returns>
	public static bool operator ==(UserIdentifier? left, UserIdentifier? right)
	{
		return Equals(left, right);
	}
	/// <summary>
	/// 判断两个 <see cref="UserIdentifier"/> 对象是否不相等。
	/// </summary>
	/// <param name="left">左侧对象。</param>
	/// <param name="right">右侧对象。</param>
	/// <returns>如果不相等则返回 true，否则返回 false。</returns>
	public static bool operator !=(UserIdentifier? left, UserIdentifier? right)
	{
		return !Equals(left, right);
	}
	/// <summary>
	/// 返回当前对象的字符串表示形式。
	/// </summary>
	/// <returns>用户标识的字符串表示，与 <see cref="ToUserIdentifierString"/> 一致。</returns>
	public override string ToString()
	{
		return ToUserIdentifierString();
	}
}